package com.cawring.simple;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cawring.simple.route.RouteVO;
import com.cawring.simple.route.Routes;

/**
 * 
 * <pre>
 * 클래스명 : 심플 서블릿 시작
 * 패키지명 : com.cawring.simple
 * 파일명   : Simple.java
 * 설명     :
 * 서블릿 로드
 * </pre>
 * @Author    : 백승건
 * @Date      : 2014. 3. 12.
 * @Version   : v.1.0.0 - 2014. 3. 12. 최초작성
 */
public class Simple extends HttpServlet {

	private static final long serialVersionUID = 201403051911L;
	
	private static final Logger log = Logger.getLogger(Simple.class.getName());
	
	/**
	 * GET
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGenerator(req, resp);
	}

	/**
	 * POST
	 */
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGenerator(req, resp);
	}
	
	/**
	 * 
	 * <pre>
	 * 메소드명     : 호출 및 응답을 대응한다.
	 * 메소드작성일 : 2014. 3. 12.
	 * 메소드설명   :
	 * GET, POST method에 대한 url 정보가 
	 * </pre>
	 * @param req   : request
	 * @param resp  : response
	 */
	public void doGenerator(HttpServletRequest req, HttpServletResponse resp)
	{
		try {
			
			/* 인코딩 선언 */
			resp.setContentType("text/html; charset=UTF-8");
			
			/* 변수선언 */
			String method = req.getMethod();
			String url    = req.getRequestURI();
			
			/* routes 정보를 가지고 온다. */
			Routes routes = Routes.getInstance();
			RouteVO vo    = routes.get(method, url);
			
			/* 해당 컨트롤러 접근 */
			Class<?> controller = Class.forName(vo.getController());
			Object instance = controller.newInstance();
			
			/* 컨트롤러 구조 */
			List<Class<?>> clazzes = new ArrayList<Class<?>>();
			clazzes.add(instance.getClass());					/* controller */
			clazzes.add(instance.getClass().getSuperclass());	/* extend */
			
			/* request, response 인스턴스변수 호출 */
			Field requestField  = null;	/* request */
			Field responseField = null; /* response */
			
			/* 클래스 파일을 검사한다. */
			for(Class<?> clazz : clazzes)
			{
				/* 클래스에 인스턴스 변수를 모두 담는다. */
				Field[] fields = clazz.getDeclaredFields();
				
				/* 인스턴스변수를 검사한다. */
				for(Field field : fields)
				{
					/* 응답, 전송 필드를 찾는다. */
					if("request".equals(field.getName())) requestField = field;
					if("response".equals(field.getName())) responseField = field;
					
					/* 필드 정보의 값을 있는 경우 */
					if(requestField != null && responseField != null)
					{
						/* 해당 필드의 setter를 찾아 메소드 선언을 한다. */
						Method setRequest  = clazz.getDeclaredMethod("setRequest", HttpServletRequest.class);
						Method setResponse = clazz.getDeclaredMethod("setResponse", HttpServletResponse.class);
						
						/* 수정 권한을 얻는다. */
						setRequest.setAccessible(true);
						setResponse.setAccessible(true);
						
						/* 값을 넣는다. invoke */
						setRequest.invoke(instance,req);
						setResponse.invoke(instance,resp);
						
						/* 더이상 찾을 필요 없음 */
						break;
					}
				}
			}
			
			/* 메소드 실행 */
			Method def = instance.getClass().getMethod(vo.getDef());
			def.invoke(instance);
			
		} catch (Exception e) {
			log.severe("routes 정보에 문제가 발생했습니다.");
		}
	}

	
}
